home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / p063b9s.zip / UNIT / OUTMAN.PAS < prev    next >
Pascal/Delphi Source File  |  1997-03-02  |  57KB  |  1,542 lines

  1. UNIT OutMan;
  2. {╔══════════════════════════════════════════════════════════════════════════╗}
  3. {║ Outbound manager                              Last changed: 02.03.97  SA ║}
  4. {║                                                                          ║}
  5. {║                         (C) Copyright 1989-97 by                         ║}
  6. {║       Dan Wulff, Jens Sandalgaard, Steen Christensen & S¢ren Ager        ║}
  7. {║                                                                          ║}
  8. {║ This source may not be given to anybody, without the written permission  ║}
  9. {║ from The Portal Team.                                                    ║}
  10. {╚══════════════════════════════════════════════════════════════════════════╝}
  11. {$I POPDEFS.INC}
  12.  
  13. INTERFACE
  14.  
  15. USES Use32;
  16.  
  17. PROCEDURE OutboundManager;
  18.  
  19. IMPLEMENTATION
  20.  
  21. USES Dos, OpCrt, OpString, OpWindow, OpRoot, OpDos, OpCmd, OpKey,
  22.      MailUtil, UnixDate, FileUtil, Display, StrUtil, Input, Keyboard,
  23.      OutUtil, InterCom, OproUtil, NetFile, Resource, SimpDB, Globals,
  24.      LogFile, Util, ArcView, PoPTypes;
  25.  
  26. TYPE
  27.   OutboundPtrType= ^OutboundEntry;
  28.   OutboundEntry  = Object(DoubleListNode)
  29.                      Address        : TFidoAddress;
  30.                      Path           : PathStr;
  31.                      Name           : S12;
  32.                      Typ,
  33.                      Stat           : Char;
  34.                      Siz            : LongInt;
  35.                      DoAfter        : String[1];
  36.                      Marked         : Boolean;
  37.  
  38.                      Constructor Init;
  39.                    END;
  40.  
  41.  
  42.   CONSTRUCTOR OutboundEntry.Init;
  43.   BEGIN
  44.     IF Not DoubleListNode.Init THEN Fail;
  45.     Address.Zone:=0; Address.Net:=0; Address.Node:=0; Address.Point:=0;
  46.     Path:=''; Name:=''; typ:=#0; Stat:=#0;
  47.     Siz:=0; DoAfter:=''; Marked:=False;
  48.   END;
  49.  
  50.   PROCEDURE OutboundManager;
  51.   CONST
  52.     Attach         : String[6] = 'HDFCI ';
  53.     Mail           : String[6] = 'HDOCI ';
  54.   VAR
  55.     NodeStr         : S13;
  56.     Outbound        : DoubleList;
  57.     FirstLine, OutboundPtr    : OutboundPtrType;
  58.     l, Linie           : Byte;
  59.     Temp, Temp3        : windowptr;
  60.     MarkCount          : Word;
  61.  
  62.     FUNCTION AddressFileName(OPtr: OutboundPtrType): PathStr;
  63.     BEGIN
  64.       AddressFileName:=HoldFileName(OPtr^.Address,False);
  65.     END;
  66.  
  67.     FUNCTION GlobalCmdMenu(VAR escaped : Boolean) : Byte;
  68.     VAR
  69.       m       : TPoPMenu;
  70.       LastCmd,
  71.       Key     : Word;
  72.     BEGIN
  73.       GetMenu(MnuOMGlobalCmd,3,m);
  74.       m.ProcessMenu(Key, LastCmd);
  75.       Escaped:=(LastCmd=ccQuit);
  76.       GlobalCmdMenu:=key;
  77.     END;
  78.  
  79.     FUNCTION GetUpdateType(VAR escaped : Boolean) : Char;
  80.     VAR
  81.       m       : TPoPMenu;
  82.       LastCmd,
  83.       Key     : Word;
  84.     BEGIN
  85.       GetMenu(MnuOMGetUpdType,3,m);
  86.       m.ProcessMenu(Key, LastCmd);
  87.       Escaped:=(LastCmd=ccQuit);
  88.       CASE Key OF
  89.         1 : GetUpdateType:='+';
  90.         2 : GetUpdateType:='-';
  91.       END;
  92.     END;
  93.  
  94.     FUNCTION SelectSendType(VAR escaped : Boolean) : Byte;
  95.     VAR
  96.       m       : TPoPMenu;
  97.       LastCmd,
  98.       key     : Word;
  99.     BEGIN
  100.       GetMenu(MnuOMSelSendAs,3,m);
  101.       m.ProcessMenu(Key, LastCmd);
  102.       Escaped:=(LastCmd=ccQuit);
  103.       SelectSendType:=Byte(key);
  104.     END;
  105.  
  106.     PROCEDURE InsertEntry;
  107.     VAR
  108.       NewOutbound : OutboundPtrType;
  109.       TmpAdr      : TFidoAddress;
  110.     BEGIN
  111.       NewOutbound:=OutboundPtr;
  112.       IF Outbound.Head = NIL THEN
  113.       BEGIN
  114.         Outbound.Append(OutboundPtr);
  115.       END ELSE
  116.       BEGIN
  117.         TmpAdr:=OutboundPtr^.Address;
  118.  
  119.         OutboundPtr:=OutboundPtrType(Outbound.Head);
  120.         WHILE (OutboundPtr<>Nil) AND (Address2Sort(OutboundPtr^.Address)<Address2Sort(TmpAdr)) DO
  121.         BEGIN
  122.           OutboundPtr:=OutboundPtrType(Outbound.Next(OutboundPtr));
  123.         END;
  124.         IF OutboundPtr=NIL THEN
  125.           OutBound.Append(NewOutBound)
  126.         ELSE
  127.           Outbound.PlaceBefore(NewOutbound, OutboundPtr);
  128.       END;
  129.       OutboundPtr:=NewOutbound;
  130.     END;
  131.  
  132.     PROCEDURE WriteLine(OPtr: OutboundPtrType; Linie: Byte; Current: BOOLEAN);
  133.     VAR
  134.       BeforePtr : OutboundPtrType;
  135.       Attr      : BYTE;
  136.     BEGIN
  137.       IF OPtr=NIL THEN Exit;
  138.       BeforePtr:=OutboundPtrType(Outbound.Prev(OPtr));
  139.       Attr:=CorrectAttribute(2,Current,OPtr^.Marked);
  140.       IF (Linie=2) OR (BeforePtr=Nil) OR Not CmpAdr(OPtr^.Address,BeforePtr^.Address) THEN
  141.       BEGIN
  142.         NodeStr:=Address2Str(OPtr^.Address) ;
  143.         Temp^.wFastWrite(' '+CPad(NodeStr,13), Linie, 1, Attr);
  144.       END ELSE
  145.          Temp^.wFastWrite('      -       ', Linie, 1, Attr);
  146.       CASE OPtr^.typ OF
  147.         'O' : Temp^.wFastWrite('OLDREQ  ', Linie, 15, Attr);
  148.         'U' : Temp^.wFastWrite('UPDREQ  ', Linie, 15, Attr);
  149.         'R' : Temp^.wFastWrite('F. REQ  ', Linie, 15, Attr);
  150.         'B' : Temp^.wFastWrite('BUNDLE  ', Linie, 15, Attr);
  151.         'M' : Temp^.wFastWrite('MAIL    ', Linie, 15, Attr);
  152.         'F' : Temp^.wFastWrite('ATTACH  ', Linie, 15, Attr);
  153.         'Z' : Temp^.wFastWrite('UNDIAL  ', Linie, 15, Attr);
  154.         'P' : Temp^.wFastWrite('POLL    ', Linie, 15, Attr);
  155.         'W' : Temp^.wFastWrite('B.WAZO  ', Linie, 15, Attr);
  156.       END;
  157.       CASE OPtr^.stat OF
  158.         'O',
  159.         'F' : Temp^.wFastWrite('NORMAL  ', Linie, 23, Attr);
  160.         'C' : Temp^.wFastWrite('CRASH   ', Linie, 23, Attr);
  161.         'H' : Temp^.wFastWrite('HOLD    ', Linie, 23, Attr);
  162.         'D' : Temp^.wFastWrite('DIRECT  ', Linie, 23, Attr);
  163.         'I' : Temp^.wFastWrite('IMPORT. ', Linie, 23, Attr);
  164.         ELSE  Temp^.wFastWrite('        ', Linie, 23, Attr);
  165.       END;
  166.       IF (OPtr^.typ = 'M') AND (OPtr^.siz = 0) THEN
  167.         Temp^.wFastWrite('Missing  ', Linie, 31, Attr)
  168.       ELSE
  169.         IF NOT(OPtr^.typ IN ['R', 'U', 'O', 'Z']) THEN
  170.         BEGIN
  171.           Temp^.wFastWrite(LongIntForm('#######',OPtr^.siz)+'  ', Linie, 31, Attr);
  172.         END ELSE
  173.           Temp^.wFastWrite('         ', Linie, 31, Attr);
  174.       Temp^.wFastWrite(CPad(OPtr^.path+OPtr^.Name,39), Linie, 40, Attr);
  175.       Temp^.wFastWrite(OPtr^.DoAfter, Linie,78,Attr);
  176.     END;
  177.  
  178.     PROCEDURE WriteOutbound;
  179.     VAR
  180.       SaveOutBound   : OutboundPtrType;
  181.       num, a         : Byte;
  182.     BEGIN
  183.       SaveOutBound:=FirstLine;
  184.       Num:=2;
  185.       WHILE (FirstLine<>NIL) AND (Num<ScreenHeight-4) DO
  186.       BEGIN
  187.         IF FirstLine=OutboundPtr THEN
  188.         BEGIN
  189.           WriteLine(FirstLine, num,FALSE);
  190.           Linie:=Num;
  191.         END ELSE
  192.           WriteLine(FirstLine, num,FALSE);
  193.         FirstLine:=OutboundPtrType(outbound.next(FirstLine));
  194.         Inc(Num);
  195.       END;
  196.       FOR a:=Num TO ScreenHeight-5 DO
  197.       BEGIN
  198.         GOTOXY(1, a); CLREOL;
  199.       END;
  200.       FirstLine:=SaveOutBound;
  201.     END;
  202.  
  203.     PROCEDURE BrowseList;
  204.     VAR
  205.       TmpPtr          : OutboundPtrType;
  206.       InKey           : Word;
  207.  
  208.       PROCEDURE UnmarkAll;
  209.       VAR
  210.         TmpPtr          : OutboundPtrType;
  211.       BEGIN
  212.         IF MarkCount>0 THEN
  213.         BEGIN
  214.           TmpPtr:=OutboundPtrType(Outbound.Head);
  215.           WHILE TmpPtr<>Nil DO
  216.           BEGIN
  217.             TmpPtr^.Marked:=False;
  218.             TmpPtr:=OutboundPtrType(Outbound.Next(TmpPtr));
  219.           END;
  220.           MarkCount:=0;
  221.         END;
  222.         WriteOutbound;
  223.       END;
  224.  
  225.       PROCEDURE AdjustFirstLine;
  226.       BEGIN
  227.         FirstLine:=OutboundPtr;
  228.         WHILE (Outbound.Prev(FirstLine)<>Nil) And (Linie>2) DO
  229.         BEGIN
  230.           Dec(Linie);
  231.           FirstLine:=OutboundPtrType(Outbound.Prev(FirstLine));
  232.         END;
  233.         UnMarkAll;
  234.       END;
  235.  
  236.       PROCEDURE SendFile;
  237.       VAR
  238.         FNum, i : Byte;
  239.         OutAddress : TFidoAddress;
  240.         p, Mask        : PathStr;
  241.         FilesToSend    : ARRAY[1..20] OF RECORD
  242.                                            FName    : PathStr;
  243.                                            SendType : Byte;
  244.                                          END;
  245.         Escaped        : Boolean;
  246.         Ch             : Char;
  247.         FName          : String[12];
  248.         Ext            : String[4];
  249.         Srec           : SEARCHREC;
  250.       BEGIN
  251.         Ch:=Attach[SelectMailType(escaped,1550)];
  252.         IF escaped THEN Exit;
  253.         OutAddress.Zone:=cfg.Addresses[Cfg.MainAdrNum].Zone;
  254.         OutAddress.Net:=cfg.Addresses[Cfg.MainAdrNum].Net;
  255.         OutAddress.Node:=0;
  256.         OutAddress.Point:=0;
  257.         IF Not GetConfirmAddress(4,3,OutAddress,1503) THEN Exit;
  258.         FillChar(FilesToSend, SizeOf(FilesToSend), 0);
  259.         FNum:=1;
  260.         Mask:='*.*';
  261.         REPEAT
  262.           FilesToSend[FNum].SendType:=SelectSendType(escaped);
  263.           IF escaped And (FNum=1) THEN Exit;
  264.           IF Not Escaped THEN
  265.           BEGIN
  266.             IF SelectFile(Mask) THEN FilesToSend[FNum].FName:=Mask;
  267.             IF FilesToSend[FNum].FName = '' THEN
  268.             BEGIN
  269.               IF FNum=1 THEN Exit;
  270.             END;
  271.             Mask:=AddBackSlash(JustPathName(Mask))+'*.*' ;
  272.           END;
  273.           Inc(FNum);
  274.         UNTIL (FNum=21) OR (FilesToSend[FNum-1].FName='');
  275.         WHILE FilesToSend[FNum].FName='' DO Dec(FNum);
  276.         FOR i:=1 TO FNum DO
  277.           SendAFile(FilesToSend[i].FName, OutAddress, Ch, FilesToSend[i].SendType);
  278.         FOR i:=1 TO FNum DO
  279.         BEGIN
  280.           New(OutboundPtr,Init);
  281.           IF OutboundPtr<>NIL THEN
  282.           BEGIN
  283.             WITH OutboundPtr^ DO
  284.             BEGIN
  285.               FSplit(FilesToSend[i].FName, p, FName, ext);
  286.               Name:=FName+ext;
  287.               Address:=OutAddress;
  288.               Stat:=Ch;
  289.               DoAfter:=STypeArray[FilesToSend[i].SendType];
  290.               FINDFIRST(FilesToSend[i].FName, AnyFile, Srec);
  291.               IF DOSERROR = 0 THEN
  292.                 siz:=Srec.size
  293.               ELSE
  294.                 siz:=0;
  295.               path:=p;
  296.               typ:='F';
  297.               FindClose(Srec);
  298.             END;
  299.             InsertEntry;
  300.           END ELSE
  301.             AddLog('!', 'OutMan: Out of memory');
  302.         END;
  303.         AdjustFirstLine;
  304.       END;
  305.  
  306.       PROCEDURE RequestFile;
  307.       VAR
  308.         ReqAddress : TFidoAddress;
  309.         ReqFiles       : ARRAY[1..20] OF RECORD
  310.                                            FName   : String[15];
  311.                                            Password: String[20];
  312.                                          END;
  313.         escaped        : Boolean;
  314.         i,FNum : Byte;
  315.         Ch : Char;
  316.       BEGIN
  317.         FillChar(ReqAddress, SizeOf(ReqAddress), 0);
  318.         ReqAddress.Zone:=Cfg.Addresses[Cfg.MainAdrNum].Zone;
  319.         ReqAddress.Net:=Cfg.Addresses[Cfg.MainAdrNum].Net;
  320.         IF Not GetConfirmAddress(4,3,ReqAddress,1504) THEN Exit;
  321.         Ch:=Attach[SelectMailType(escaped,1551)];
  322.         IF escaped THEN Exit;
  323.         FillChar(ReqFiles, SizeOf(ReqFiles), 0);
  324.         FNum:=1;
  325.         REPEAT
  326.           IF (NOT InputString(10,5,15,15,3,'Request file','',ReqFiles[FNum].FName)) OR (ReqFiles[FNum].FName = '') THEN
  327.             IF FNum=1 THEN Exit ELSE Break;
  328.           ReqFiles[FNum].FName:= StUpCase(ReqFiles[FNum].FName);
  329.           IF (NOT InputString(24,5,20,20,3,'Passwd','',ReqFiles[FNum].PassWord)) THEN
  330.             IF FNum=1 THEN Exit ELSE Break;
  331.           INC(FNum);
  332.         UNTIL FNum=21;
  333.         Dec(FNum);
  334.         FOR i:=1 TO FNum DO
  335.           IF NOT RequestAFile(ReqFiles[i].FName, ReqAddress, ReqFiles[i].Password) THEN
  336.             ReqFiles[i].FName:='';
  337.  
  338.         FOR i:=1 TO FNum DO
  339.         BEGIN
  340.           IF ReqFiles[i].FName<>'' THEN
  341.           BEGIN
  342.             New(outboundPtr, Init);
  343.             IF OutboundPtr<>NIL THEN
  344.             BEGIN
  345.               WITH OutboundPtr^ DO
  346.               BEGIN
  347.                 Name:=ReqFiles[i].FName;
  348.                 Address:=ReqAddress;
  349.                 typ:='R';
  350.                 siz:=0;
  351.               END;
  352.               InsertEntry;
  353.             END ELSE
  354.               AddLog('!', 'OutMan: Out of memory');
  355.           END;
  356.         END;
  357.         IF MakeAPoll(ReqAddress,Ch) THEN
  358.         BEGIN
  359.           New(OutboundPtr,Init);
  360.           IF OutboundPtr<>NIL THEN
  361.           BEGIN
  362.             WITH OutboundPtr^ DO
  363.             BEGIN
  364.               Address:=ReqAddress;
  365.               Typ:='P';
  366.               Stat:=Ch;
  367.               Siz:=0;
  368.             END;
  369.             InsertEntry;
  370.           END ELSE
  371.             AddLog('!', 'OutMan: Out of memory');
  372.         END;
  373.         AdjustFirstLine;
  374.       END;
  375.  
  376.       PROCEDURE DeleteEntry;
  377.       VAR
  378.         BadWaZOORec    : TBadWaZOO;
  379.         BadWaZOOFile   : PSimpDB;
  380.         CPtr, TmpPtr   : OutboundPtrType;
  381.         Srec           : SEARCHREC;
  382.         Ch             : Char;
  383.         TempFile       : File;
  384.         TempFile2      : PBufTextFile;
  385.         Count          : Byte;
  386.         InStr          : String;
  387.         DoIt, All,
  388.         Found, Del     : Boolean;
  389.         FName          : PathStr;
  390.       BEGIN
  391.         IF (MarkCount=0) And (Outbound.Size>0) THEN
  392.         BEGIN
  393.           OutboundPtr^.Marked:=True;
  394.           Inc(MarkCount);
  395.         END;
  396.         CPtr:=OutboundPtrType(Outbound.Head);
  397.         All:=False;
  398.         WHILE CPtr<>Nil DO
  399.         BEGIN
  400.           IF CPtr^.Marked THEN
  401.           BEGIN
  402.             DoIt:=True;
  403.             IF NOT All THEN
  404.             BEGIN
  405.               CASE ConfirmAll(' Delete mail for '+Address2Str(CPtr^.Address)+' ?', 10) OF
  406.                 'Y' : DoIt:=True;
  407.                 'N' : DoIt:=False;
  408.                 'A' : All:=True;
  409.               END;
  410.             END;
  411.             IF DoIt THEN
  412.             BEGIN
  413.               CASE CPtr^.Typ OF
  414.                 'B' : DeleteFile(HoldAreaPath(CPtr^.Address,False)+CPtr^.Name);
  415.                 'Z' : WITH CPtr^ DO
  416.                         RemoveUnDialable(Address);
  417.                 'W' : BEGIN
  418.                         New(BadWaZOOFile, Open(StartPath+PoPBadWaZooFileName, SizeOf(TBadWaZOO), False));
  419.                         IF BadWaZooFile<>Nil THEN
  420.                         BEGIN
  421.                           Found:=False;
  422.                           WHILE NOT Found AND BadWaZooFile^.NextRec(BadWaZOORec, Keep) DO
  423.                           BEGIN
  424.                             IF CmpAdr(BadWaZooRec.Address,CPtr^.Address) AND
  425.                                (CPtr^.Name=BadWaZOORec.NewName) THEN
  426.                               Found := True
  427.                             ELSE
  428.                               BadWaZooFile^.Unlock(BadWaZOOFile^.FilePos-1);
  429.                           END;
  430.                           IF Found THEN
  431.                           BEGIN
  432.                             DeleteFile(Cfg.Inbound[BadWaZooRec.NodeStat]+BadWaZooRec.NewName);
  433.                             BadWaZooFile^.DelRec(BadWaZooRec, BadWaZooFile^.FilePos-1);
  434.                           END;
  435.                           Dispose(BadWaZOOFile, Close);
  436.                         END;
  437.                       END;
  438.                 ELSE BEGIN
  439.                        FileMode:=ShareRW+ShareDenyW;
  440.                        IF (CPtr^.typ IN ['R', 'U', 'O']) THEN
  441.                          Assign(TempFile, AddressFileName(CPtr)+'REQ')
  442.                        ELSE
  443.                          Assign(TempFile, AddressFileName(CPtr)+CPtr^.Stat+'LO');
  444.                        Reset(TempFile, 1);
  445.                        New(TempFile2, Init(AddressFileName(CPtr)+'TMP',SCreate,2048));
  446.                        Found:=False;
  447.                        Count:=0;
  448.                        WHILE NOT EoF(TempFile) DO
  449.                        BEGIN
  450.                          ReadLine(TempFile, InStr);
  451.                          IF Copy(InStr,1,1)<>'~' THEN
  452.                          BEGIN
  453.                            IF (InStr[1] = '#') OR (InStr[1] = '^') THEN
  454.                            BEGIN
  455.                              Del:=True;
  456.                              Ch:=InStr[1];
  457.                              Delete(InStr, 1, 1);
  458.                            END ELSE
  459.                              Del:=False;
  460.                            IF Pos(' ', InStr)>0 THEN FName:=Copy(InStr, 1, pos(' ', InStr)-1) ELSE FName:=InStr;
  461.                            IF ((StUpCase(FName)<>StUpCase(CPtr^.path+CPtr^.Name)) AND
  462.                                (StUpCase(FName)<>StUpCase(HoldAreaPath(CPtr^.Address,False)+CPtr^.Name)))
  463.                                OR (Found) THEN
  464.                            BEGIN
  465.                              IF Del THEN TempFile2^.WriteLn(Ch+InStr) ELSE TempFile2^.WriteLn(InStr);
  466.                              Inc(Count);
  467.                            END ELSE
  468.                            BEGIN
  469.                              IF NOT Found THEN
  470.                              BEGIN
  471.                                Found:=True;
  472.                                IF Del And (CPtr^.Siz>0) THEN
  473.                                BEGIN
  474.                                  DoIt:=True;
  475.                                  IF NOT All THEN
  476.                                  BEGIN
  477.                                    CASE ConfirmAll(' Delete '+CPtr^.Name+' too?', 10) OF
  478.                                      'Y' : DoIt:=True;
  479.                                      'N' : DoIt:=False;
  480.                                      'A' : All:=True;
  481.                                    END;
  482.                                  END;
  483.                                  IF DoIt THEN DeleteFile(InStr);
  484.                                END;
  485.                              END;
  486.                            END;
  487.                          END;
  488.                        END;
  489.                        Close(TempFile); Dispose(TempFile2, Done);
  490.                        IF CPtr^.typ IN ['R', 'U', 'O'] THEN
  491.                        BEGIN
  492.                          DeleteFile(AddressFileName(CPtr)+'REQ');
  493.                        END ELSE
  494.                          DeleteFile(AddressFileName(CPtr)+CPtr^.stat+'LO');
  495.                        IF Count=0 THEN
  496.                        BEGIN
  497.                          DeleteFile(AddressFileName(CPtr)+'TMP');
  498.                          FINDFIRST(AddressFileName(CPtr)+CPtr^.stat+'LO', AnyFile, Srec);
  499.                          IF DOSERROR = 0 THEN
  500.                            IF Srec.size = 0 THEN
  501.                            BEGIN
  502.                              DeleteFile(AddressFileName(CPtr)+CPtr^.stat+'LO');
  503.                            END;
  504.                          FindClose(SRec);
  505.                        END ELSE
  506.                        BEGIN
  507.                          IF (CPtr^.typ IN ['R', 'U', 'O']) THEN
  508.                            RenameFile(AddressFileName(CPtr)+'TMP', AddressFileName(CPtr)+'REQ')
  509.                          ELSE
  510.                            RenameFile(AddressFileName(CPtr)+'TMP', AddressFileName(CPtr)+CPtr^.stat+'LO');
  511.                        END;
  512.                      END; {case else}
  513.               END;
  514.               TmpPtr:=CPtr;
  515.               IF Outbound.Next(CPtr)=Nil THEN
  516.                 CPtr:=OutboundPtrType(Outbound.Prev(CPtr))
  517.               ELSE
  518.                 CPtr:=OutboundPtrType(Outbound.Next(CPtr));
  519.               IF FirstLine=TmpPtr THEN FirstLine:=CPtr;
  520.               IF TmpPtr=OutboundPtr THEN OutboundPtr:=CPtr;
  521.               Outbound.Delete(TmpPtr);
  522.             END ELSE
  523.               CPtr:=OutboundPtrType(Outbound.Next(CPtr));
  524.           END ELSE
  525.             CPtr:=OutboundPtrType(Outbound.Next(CPtr));
  526.         END;
  527.         UnmarkAll;
  528.       END;
  529.  
  530.       PROCEDURE MergeBundles(CONST OldName, NewName: PathStr);
  531.       VAR
  532.         Old,New : TNetFile;
  533.         Buffer  : Pointer;
  534.         BufSize, Got : Word;
  535.         Cptr    : OutboundPtrType;
  536.       BEGIN
  537.         Old.Open(OldName, 1, False);
  538.         New.Open(NewName, 1, False);
  539.  
  540.         New.Seek(New.FileSize-2);
  541.         Old.Seek(SizeOf(TPktHeader));
  542.         IF MaxAvail>65000 THEN BufSize:=65000 ELSE BufSize:=MaxAvail;
  543.         GetMem(Buffer,BufSize);
  544.         REPEAT
  545.           Old.BlockReadNum(Buffer^,BufSize,Got);
  546.           New.BlockWrite(Buffer^,Got);
  547.         UNTIL Got=0;
  548.         CPtr:=OutboundPtrType(Outbound.Head);
  549.         WHILE (CPtr<>NIL) AND (Cptr^.Typ<>'B') AND (AddressFileName(CPtr)+CPtr^.stat+'UT'<>NewName) DO
  550.           Cptr:=OutboundPtrType(Outbound.Next(Cptr));
  551.         IF Cptr<>NIL THEN Cptr^.Siz:=New.FILESIZE;
  552.         Old.Close; New.Close;
  553.         DeleteFile(OldName);
  554.         FreeMem(Buffer,BufSize);
  555.       END;
  556.  
  557.       PROCEDURE ReAddress;
  558.       VAR
  559.         OldName,
  560.         NewName  : PathStr;
  561.         Count : Byte;
  562.         CPtr       : OutboundPtrType;
  563.         NewAddress : TFidoAddress;
  564.         All, DoIt,
  565.         RemoveIt, Del : Boolean;
  566.         OldFile,
  567.         NewFile, Tmp : PBufTextFile;
  568.         InSTr : String;
  569.         Ch    : Char;
  570.       BEGIN
  571.         IF ((MarkCount=0) AND (OutboundPtr^.Typ IN ['Z','W'])) OR (Outbound.Size<1) THEN Exit;
  572.         NewAddress:=OutboundPtr^.Address;
  573.         IF NOT GetConfirmAddress(4,3,NewAddress,1505) OR CmpAdr(NewAddress,OutboundPtr^.Address) THEN Exit;
  574.         IF MarkCount=0 THEN
  575.         BEGIN
  576.           OutboundPtr^.Marked:=True;
  577.           Inc(MarkCount);
  578.         END;
  579.         CPtr:=OutboundPtrType(Outbound.Head);
  580.         All:=False;
  581.         WHILE CPtr<>Nil DO
  582.         BEGIN
  583.           RemoveIt:=False;
  584.           IF CPtr^.Marked THEN
  585.           BEGIN
  586.             CASE CPtr^.typ OF
  587.               'P' : BEGIN
  588.                       IF NOT ExistFile(HoldFileName(NewAddress,True)+CPtr^.Stat+'LO') THEN
  589.                       BEGIN
  590.                         RenameFile(AddressFileName(CPtr)+CPtr^.stat+'LO',
  591.                                    HoldFileName(NewAddress,True)+CPtr^.stat+'LO');
  592.                       END ELSE
  593.                         DeleteFile(AddressFileName(CPtr)+CPtr^.stat+'LO');
  594.                     END;
  595.               'B' : BEGIN
  596.                       IF NOT ExistFile(HoldFileName(NewAddress,True)+CPtr^.stat+'UT') THEN
  597.                       BEGIN
  598.                         RenameFile(AddressFileName(CPtr)+CPtr^.stat+'UT',
  599.                                       HoldFileName(NewAddress,True)+CPtr^.stat+'UT');
  600.                       END ELSE
  601.                       BEGIN
  602.                         DoIt:=True;
  603.                         IF NOT All THEN
  604.                         BEGIN
  605.                           CASE ConfirmAll('Merge bundles', 11) OF
  606.                             'Y' : DoIt:=True;
  607.                             'N' : DoIt:=False;
  608.                             'A' : All:=True;
  609.                           END;
  610.                         END;
  611.                         IF DoIt THEN
  612.                         BEGIN
  613.                           MergeBundles(AddressFileName(CPtr)+CPtr^.stat+'UT',
  614.                                        HoldFileName(NewAddress,True)+CPtr^.stat+'UT');
  615.                         END;
  616.                         RemoveIt:=True;
  617.                       END;
  618. {                     CPtr^.Name:=JustFileName(HoldFileName(NewAddress,True)+CPtr^.stat+'UT');}
  619.                     END;
  620.               'R',
  621.               'U',
  622.               'O',
  623.               'M',
  624.               'F' : BEGIN
  625.                       IF CPtr^.Typ IN ['R','U','O'] THEN
  626.                       BEGIN
  627.                         OldName:=AddressFileName(CPtr)+'REQ';
  628.                         NewName:=HoldFileName(NewAddress,True)+'REQ';
  629.                       END ELSE
  630.                       BEGIN
  631.                         OldName:=AddressFileName(CPtr)+CPtr^.Stat+'LO';
  632.                         NewName:=HoldFileName(NewAddress,True)+CPtr^.Stat+'LO';
  633.                       END;
  634.                       New(Tmp, Init(AddressFilename(CPtr)+'TMP', SCreate, 2048));
  635.                       New(OldFile, Init(OldName, SOpenRead+ShareDenyW, 2048));
  636.                       IF OldFile<>NIL THEN
  637.                       BEGIN
  638.                         New(NewFile, InitCreate(NewName, SOpenWrite, 2048));
  639.                         Count:=0;
  640.                         WHILE NOT OldFile^.EOF DO
  641.                         BEGIN
  642.                           OldFile^.ReadLn(InStr);
  643.                           IF (InStr[1] = '#') OR (InStr[1] = '^') THEN
  644.                           BEGIN
  645.                             Del:=True;
  646.                             Ch:=InStr[1];
  647.                             Delete(InStr, 1, 1);
  648.                           END ELSE
  649.                             Del:=False;
  650.                           IF (StUpCase(InStr) <> StUpCase(CPtr^.path+CPtr^.Name)) AND
  651.                              (StUpCase(InStr) <> StUpCase(HoldAreaPath(CPtr^.Address,False)+CPtr^.Name)) THEN
  652.                           BEGIN
  653.                             IF Del THEN Tmp^.WriteLn(Ch+InStr) ELSE Tmp^.WriteLn(InStr);
  654.                             Inc(Count);
  655.                           END ELSE
  656.                           BEGIN
  657.                             IF Del THEN NewFile^.WriteLn(Ch+InStr) ELSE NewFile^.WriteLn(InStr);
  658.                           END;
  659.                         END;
  660.                         Dispose(OldFile, Done); Dispose(NewFile, Done);
  661.                         DeleteFile(OldName);
  662.                       END ELSE
  663.                         Count:=0;
  664.                       Dispose(Tmp, Done);
  665.                       IF Count = 0 THEN
  666.                       BEGIN
  667.                         DeleteFile(AddressFilename(CPtr)+'TMP');
  668.                       END ELSE
  669.                       BEGIN
  670.                         IF CPtr^.Typ IN ['R','U','O'] THEN
  671.                           RenameFile(AddressFileName(CPtr)+'TMP', AddressFileName(CPtr)+'REQ')
  672.                         ELSE
  673.                           RenameFile(AddressFileName(CPtr)+'TMP', AddressFileName(CPtr)+CPtr^.stat+'LO');
  674.                       END;
  675.                     END;
  676.             END;
  677.             OutboundPtr:=CPtr;
  678.             Outbound.Remove(CPtr);
  679.             IF RemoveIt THEN
  680.               Dispose(OutboundPtr)
  681.             ELSE
  682.             BEGIN
  683.               WITH OutboundPtr^ DO
  684.               BEGIN
  685.                 Address:=NewAddress;
  686.               END;
  687.               InsertEntry;
  688.               CPtr:=OutboundPtr;
  689.               CPtr^.Marked:=False;
  690.             END;
  691.             CPtr:=OutboundPtrType(Outbound.Head);
  692.           END ELSE
  693.             CPtr:=OutboundPtrType(Outbound.Next(CPtr));
  694.         END;
  695.         UnMarkAll;
  696.         FirstLine:=OutboundPtrType(Outbound.Head);
  697.         OutboundPtr:=FirstLine;
  698.         WriteOutbound;
  699.       END;
  700.  
  701.       PROCEDURE ChangeStat;
  702.       LABEL
  703.         NextOne;
  704.       VAR
  705.         TempFile       : File;
  706.         TempFile2,
  707.         TempFile3      : PBufTextFile;
  708.         InStr          : String;
  709.         Ch             : Char;
  710.         NewName        : S12;
  711.         Count, StatNum : Byte;
  712.         All, DoIt,
  713.         MustRepaint,
  714.         Del, Escaped   : Boolean;
  715.         CPtr           : OutboundPtrType;
  716.       BEGIN
  717.         IF ((MarkCount=0) And (OutboundPtr^.Typ IN ['W','R','U','O','Z'])) Or
  718.            (Outbound.Size<1) THEN Exit;
  719.         StatNum:=SelectMailType(escaped,1552);
  720.         IF Escaped THEN Exit;
  721.         IF (MarkCount=0) And (Outbound.Size>0) THEN
  722.         BEGIN
  723.           OutboundPtr^.Marked:=True;
  724.           Inc(MarkCount);
  725.         END;
  726.         CPtr:=OutboundPtrType(Outbound.Head);
  727.         MustRepaint:=False;
  728.         All:=False;
  729.         WHILE CPtr<>Nil DO
  730.         BEGIN
  731.           IF CPtr^.Marked And NOT (CPtr^.Typ IN ['W','R','U','O','Z']) THEN
  732.           BEGIN
  733.             IF CPtr^.Typ='B' THEN
  734.             BEGIN
  735.               IF Mail[StatNum] = CPtr^.Stat THEN Goto NextOne;
  736.               NewName:=Copy(CPtr^.Name, 1, 9)+Mail[StatNum]+'UT';
  737.               IF ExistFile(HoldAreaPath(CPtr^.Address,False)+NewName) THEN
  738.               BEGIN
  739.                 DoIt:=True;
  740.                 IF NOT All THEN
  741.                 BEGIN
  742.                   CASE ConfirmAll('Merge bundles', 11) OF
  743.                     'Y' : DoIt:=True;
  744.                     'N' : DoIt:=False;
  745.                     'A' : All:=True;
  746.                   END;
  747.                 END;
  748.                 IF DoIt THEN
  749.                 BEGIN
  750.                   MergeBundles(HoldAreaPath(CPtr^.Address,False)+CPtr^.Name,
  751.                                HoldAreaPath(CPtr^.Address,False)+NewName);
  752.                   Outbound.Remove(CPtr);
  753.                   Dispose(CPtr);
  754.                   CPtr:=OutboundPtrType(Outbound.Head);
  755.                   OutboundPtr:=CPtr;
  756.                   FirstLine:=CPtr;
  757.                   MustRepaint:=True;
  758.                   Continue;
  759.                 END;
  760.               END ELSE
  761.               BEGIN
  762.                 RenameFile(HoldAreaPath(CPtr^.Address,False)+CPtr^.Name,
  763.                            HoldAreaPath(CPtr^.Address,False)+NewName);
  764.                 CPtr^.Name:=NewName;
  765.                 CPtr^.Stat:=Mail[StatNum];
  766.               END ;
  767.             END ELSE
  768.             BEGIN
  769.               IF Attach[StatNum] = CPtr^.stat THEN GOTO NextOne;
  770.               Assign(TempFile, AddressFileName(CPtr)+CPtr^.stat+'LO');
  771.               FileMode:=ShareRW+ShareDenyW; Reset(TempFile,1);
  772.               IF IOResult=0 THEN
  773.               BEGIN
  774.                 New(TempFile2, Init(AddressFileName(CPtr)+'TMP', SCreate, 1024));
  775.                 New(TempFile3, InitCreate(AddressFileName(CPtr)+Attach[StatNum]+'LO', SOpenWrite+ShareDenyW, 1024));
  776.                 Count:=0;
  777.                 WHILE NOT EoF(TempFile) DO
  778.                 BEGIN
  779.                   ReadLine(TempFile, InStr);
  780.                   IF (InStr[1] = '#') OR (InStr[1] = '^') THEN
  781.                   BEGIN
  782.                     Del:=True;
  783.                     Ch:=InStr[1];
  784.                     Delete(InStr, 1, 1);
  785.                   END ELSE
  786.                     Del:=False;
  787.                   IF (StUpCase(InStr) <> StUpCase(CPtr^.path+CPtr^.Name)) AND
  788.                      (StUpCase(InStr)<>StUpCase(HoldAreaPath(CPtr^.Address,False)+CPtr^.Name)) THEN
  789.                   BEGIN
  790.                     IF Del THEN TempFile2^.WriteLn(Ch+InStr) ELSE TempFile2^.WriteLn(InStr);
  791.                     Inc(Count);
  792.                   END ELSE
  793.                   BEGIN
  794.                     IF Del THEN TempFile3^.WriteLn(Ch+InStr) ELSE TempFile3^.WriteLn(InStr);
  795.                   END;
  796.                 END;
  797.                 Close(TempFile);
  798.                 Dispose(TempFile2, Done); Dispose(TempFile3, Done);
  799.                 DeleteFile(AddressFileName(CPtr)+CPtr^.stat+'LO');
  800.                 IF Count = 0 THEN
  801.                 BEGIN
  802.                   DeleteFile(AddressFileName(CPtr)+'TMP');
  803.                 END ELSE
  804.                 BEGIN
  805.                   RenameFile(AddressFileName(CPtr)+'TMP', AddressFileName(CPtr)+CPtr^.stat+'LO');
  806.                 END;
  807.               END;
  808.               CPtr^.Stat:=Attach[StatNum];
  809.             END;
  810.           END;
  811. NextOne:
  812.           CPtr^.Marked:=False;
  813.           CPtr:=OutboundPtrType(Outbound.Next(CPtr));
  814.         END;
  815.         UnmarkAll;
  816.         IF MustRepaint THEN WriteOutbound;
  817.       END;
  818.  
  819.       PROCEDURE Poll;
  820.       VAR
  821.         PollAddress : TFidoAddress;
  822.         escaped        : Boolean;
  823.         Ch             : Char;
  824.       BEGIN
  825.         PollAddress.Zone:=Cfg.Addresses[Cfg.MainAdrNum].Zone;
  826.         PollAddress.Net:=Cfg.Addresses[Cfg.MainAdrNum].Net;
  827.         PollAddress.Node:=0;
  828.         PollAddress.Point:=0;
  829.         IF Not GetConfirmAddress(4,3,PollAddress,1506) THEN Exit;
  830.         Ch:=Attach[SelectMailType(escaped,1553)];
  831.         IF escaped THEN Exit;
  832.         IF MakeAPoll(PollAddress, Ch) THEN
  833.         BEGIN
  834.           New(OutboundPtr, Init);
  835.           IF OutboundPtr<>NIL THEN
  836.           BEGIN
  837.             WITH OutboundPtr^ DO
  838.             BEGIN
  839.               Name:='';
  840.               Address:=PollAddress;
  841.               Typ:='P';
  842.               Stat:=Ch;
  843.               Siz:=0;
  844.             END;
  845.             InsertEntry;
  846.           END ELSE
  847.             AddLog('!', 'OutMan: Out of memory');
  848.           AdjustFirstLine;
  849.         END;
  850.       END;
  851.  
  852.       PROCEDURE BundleView(CONST FName: PathStr);
  853.       VAR
  854.         BundleWin: WindowPtr;
  855.         BundleFile : File;
  856.         BPos, BytesRead: Word;
  857.         Buffer     : Pointer;
  858.  
  859.         PROCEDURE WriteBundleHeader;
  860.         VAR
  861.           BundleHeadRec : TPktHeader;
  862.         BEGIN
  863.           Move(Buffer^, BundleHeadRec, SizeOf(BundleHeadRec));
  864.           WITH BundleHeadRec DO
  865.           BEGIN
  866.             GotoXY(1,1); WriteLn(' PacketType: ',Filler1,'  Packer: ',ProductNames(Product),'  SerialNo: ',SerialNo,
  867.                                  '  Password: ',AsciiZ2Str(Password,8));
  868.             GotoXY(1,2); WriteLn(' To: ',DestZone,':',DestNet,'/',DestNode,'  From: ',OrigZone,':',OrigNet,'/',OrigNode,
  869.                                  '  Date: ',Day,'/',Month,'-',Year,'  ',Hour,':',Min,':',Sec);
  870.           END;
  871.         END;
  872.  
  873.       BEGIN
  874.         IF Not ExistFile(FName) THEN Exit;
  875.         MyWin(BundleWin, 1, 2, 80, ScreenHeight, 3, 'Bundle Viewer',False);
  876.         Assign(BundleFile, FName); FileMode:=ShareRead+ShareDenyNone;
  877.         Reset(BundleFile, 1);
  878.         GetMem(Buffer, 8192);
  879.         BlockRead(BundleFile,Buffer^, 8192, BytesRead);
  880.         Close(BundleFile);
  881.         WriteBundleHeader;
  882.         BPos:=58;
  883.  
  884.         PopReadKeyWord;
  885.         FreeMem(Buffer, 8192);
  886.         KillWindow(BundleWin);
  887.       END;
  888.  
  889.       PROCEDURE ViewFile;
  890.       VAR
  891.         AT    : ShortInt;
  892.         FName : PathStr;
  893.       BEGIN
  894.         CASE OutboundPtr^.Typ OF
  895.           'O',
  896.           'U',
  897.           'R',
  898.           'Z',
  899.           'W',
  900.           'P' : AskError(12, 'Can''t display this type of file', 3);
  901.           'B' : BundleView(HoldAreaPath(OutboundPtr^.Address,False)+OutboundPtr^.Name);
  902.           'M',
  903.           'F' : BEGIN
  904.                   IF OutboundPtr^.Typ='M' THEN
  905.                     FName:=HoldAreaPath(OutboundPtr^.Address,False)
  906.                   ELSE
  907.                     FName:=OutboundPtr^.Path;
  908.                   FName:=FName+OutboundPtr^.Name;
  909.                   AT:=ArcType(FName);
  910.                   IF AT<>0 THEN ViewArchive(FName,AT) ELSE AskError(12, 'Unknown archive type', 3);
  911.                 END;
  912.         END;
  913.       END;
  914.  
  915.       PROCEDURE FileUpdateRequest;
  916.       VAR
  917.         Password       : String[20];
  918.         ReqFile        : PBufTextFile;
  919.         Srec           : SEARCHREC;
  920.         mask, FileName, p : PathStr;
  921.         n, ext         : String[12];
  922.         UpdAddress     : TFidoAddress;
  923.         escaped        : Boolean;
  924.         Dt             : DateTime;
  925.         Ch, UpdType        : Char;
  926.       BEGIN
  927.         UpdType:=GetUpdateType(escaped);
  928.         IF escaped THEN Exit;
  929.         mask:='*.*';
  930.         IF NOT InputString(10,5,40,40,3,'Send file name','',mask) THEN Exit;
  931.         IF SelectFile(Mask) THEN FileName:=Mask ELSE FileName:='';
  932.         IF FileName = '' THEN Exit;
  933.         Ch:=Attach[SelectMailType(escaped,1551)];
  934.         IF escaped THEN Exit;
  935.         Password:='';
  936.         IF (NOT InputString(24,5,6,6,3,'Passwd','',PassWord)) THEN Exit;
  937.  
  938.         UpdAddress.Zone:=cfg.Addresses[Cfg.MainAdrNum].Zone;
  939.         UpdAddress.Net:=cfg.Addresses[Cfg.MainAdrNum].Net;
  940.         UpdAddress.Node:=0;
  941.         UpdAddress.Point:=0;
  942.         IF Not GetConfirmAddress(4,3,UpdAddress,1504) THEN Exit;
  943.         FINDFIRST(FileName, AnyFile, Srec);
  944.         FindClose(SRec);
  945.         FSplit(FileName, p, n, ext);
  946.         New(ReqFile, InitCreate(HoldFileName(UpdAddress,True)+'REQ', SOpenWrite, 256));
  947.         UnPackTime(Srec.Time, Dt);
  948.         WITH Dt DO
  949.           ReqFile^.WriteNoLn(n+ext+' '+UpdType+Long2Str(GetUnixDate(Year, Month, Day, Hour, Min, Sec)));
  950.         IF Password='' THEN ReqFile^.WriteLn('') ELSE ReqFile^.WriteLn(' !'+Password);
  951.         Dispose(ReqFile, Done);
  952.  
  953.         MakeAPoll(UpdAddress, Ch);
  954.         New(OutboundPtr, Init);
  955.         IF OutboundPtr<>NIL THEN
  956.         BEGIN
  957.           WITH OutboundPtr^ DO
  958.           BEGIN
  959.             Name:=n+ext;
  960.             Address:=UpdAddress;
  961.             CASE UpdType OF
  962.               '+' : typ:='U';
  963.               '-' : typ:='O';
  964.             END;
  965.             stat:=Ch;
  966.             siz:=0;
  967.           END;
  968.           InsertEntry;
  969.         END ELSE
  970.           AddLog('!', 'OutMan: Out of memory');
  971.         AdjustFirstLine;
  972.       END;
  973.  
  974.       PROCEDURE GlobalCmd;
  975.       CONST
  976.         DayType : ARRAY[1..7] Of String[2] = ('MO','TU','WE','TH','FR','SA','SU');
  977.       VAR
  978.         i, Choice : Byte;
  979.         Escaped: Boolean;
  980.         Sr1, SRec   : SearchRec;
  981.         BasePath, OutPath : PathStr;
  982.         TmpPtr : OutboundPtrType;
  983.  
  984.         PROCEDURE CleanTheOutbound(CONST Path: PathStr);
  985.         VAR
  986.           Sr : SearchRec;
  987.           DayCount : Byte;
  988.         BEGIN
  989.           FOR DayCount:=1 TO 7 DO
  990.           BEGIN
  991.             FindFirst(Path+'\????????.'+DayType[DayCount]+'?',AnyFile,Sr);
  992.             WHILE DosError=0 DO
  993.             BEGIN
  994.               IF (Sr.Size=0) THEN DeleteFile(Path+'\'+Sr.Name);
  995.               FindNext(Sr);
  996.             END;
  997.             FindClose(Sr);
  998.           END;
  999.         END;
  1000.  
  1001.       BEGIN
  1002.         {Clean outbound, remove undialables, }
  1003.         Choice:=GlobalCmdMenu(Escaped);
  1004.         IF Escaped THEN Exit;
  1005.         CASE Choice OF
  1006.           1: BEGIN
  1007.                i:=Length(JustFileName(cfg.outbound));
  1008.                BasePath:=Copy(Cfg.Outbound, 1, Length(Cfg.Outbound)-i);
  1009.                FindFirst(cfg.outbound+'.*', Directory, Srec);
  1010.                WHILE DOSError=0 DO
  1011.                BEGIN
  1012.                  OutPath:=BasePath+SRec.Name;
  1013.                  CleanTheOutbound(OutPath);
  1014.                  FindFirst(OutPath+'\????????.PNT', Directory, Sr1);
  1015.                  WHILE DOSError=0 DO
  1016.                  BEGIN
  1017.                    CleanTheOutbound(OutPath+'\'+Sr1.Name);
  1018.                    IF NOT Cfg.KeepEmptyDirs THEN
  1019.                    BEGIN
  1020.                      RmDir(OutPath+'\'+Sr1.Name);
  1021.                      IF IOResult<>0 THEN ;
  1022.                    END;
  1023.                    FindNext(Sr1);
  1024.                  END;
  1025.                  FindClose(Sr1);
  1026.                  IF OutPath<>Cfg.Outbound THEN
  1027.                  BEGIN
  1028.                    RmDir(OutPath);
  1029.                    IF IOResult<>0 THEN ;
  1030.                  END;
  1031.                  FindNext(SRec);
  1032.                END;
  1033.                FindClose(SRec);
  1034.              END;
  1035.           2: IF DeleteFile(StartPath+PoPUndialFileName) THEN
  1036.              BEGIN
  1037.                OutboundPtr:=OutboundPtrType(Outbound.Head);
  1038.                WHILE OutboundPtr<>Nil DO
  1039.                BEGIN
  1040.                  TmpPtr:=OutboundPtr;
  1041.                  OutboundPtr:=OutboundPtrType(Outbound.Next(OutboundPtr));
  1042.                  IF TmpPtr^.Typ='Z' THEN Outbound.Delete(TmpPtr);
  1043.                END;
  1044.              END;
  1045.         END;
  1046.         UnMarkAll;
  1047.         OutboundPtr:=OutboundPtrType(OutBound.Head);
  1048.         FirstLine:=OutboundPtr;
  1049.         WriteOutbound;
  1050.       END;
  1051.  
  1052.     BEGIN
  1053.       REPEAT
  1054.         Topic:=61;
  1055.         WriteLine(OutboundPtr, Linie,TRUE);
  1056.         InKey:=PopReadKeyWord;
  1057.         WriteLine(OutboundPtr, Linie,FALSE);
  1058.         CASE Char(Lo(Inkey)) OF
  1059.           '+' : IF Outbound.Size>0 THEN
  1060.                 BEGIN
  1061.                   TmpPtr:=OutboundPtrType(Outbound.Head);
  1062.                   WHILE TmpPtr<>Nil DO
  1063.                   BEGIN
  1064.                     IF CmpAdr(OutboundPtr^.Address,TmpPtr^.Address) And Not(TmpPtr^.Marked) THEN
  1065.                     BEGIN
  1066.                       TmpPtr^.Marked:=True;
  1067.                       Inc(MarkCount);
  1068.                     END;
  1069.                     TmpPtr:=OutboundPtrType(Outbound.Next(TmpPtr));
  1070.                   END;
  1071.                   WriteOutbound;
  1072.                 END;
  1073.           '-' : IF Outbound.Size>0 THEN
  1074.                 BEGIN
  1075.                   TmpPtr:=OutboundPtrType(Outbound.Head);
  1076.                   WHILE TmpPtr<>Nil DO
  1077.                   BEGIN
  1078.                     IF CmpAdr(OutboundPtr^.Address,TmpPtr^.Address) And (TmpPtr^.Marked) THEN
  1079.                     BEGIN
  1080.                       TmpPtr^.Marked:=False;
  1081.                       Dec(MarkCount);
  1082.                     END;
  1083.                     TmpPtr:=OutboundPtrType(Outbound.Next(TmpPtr));
  1084.                   END;
  1085.                   WriteOutbound;
  1086.                 END;
  1087.           #13 : IF Outbound.Size>0 THEN
  1088.                 BEGIN
  1089.                   OutboundPtr^.Marked:=Not OutboundPtr^.Marked;
  1090.                   Inc(MarkCount);
  1091.                   WriteLine(OutboundPtr, Linie,FALSE);
  1092.                   IF Outbound.Next(OutboundPtr)<>Nil THEN StuffKey($5000);
  1093.                 END;
  1094.           ' ' : UnmarkAll;
  1095.           ELSE CASE InKey OF
  1096.                  Up   : IF (OutboundPtr<>Nil) AND (outbound.Prev(OutboundPtr) <> NIL) THEN
  1097.                         BEGIN
  1098.                           WriteLine(OutboundPtr, Linie, FALSE);
  1099.                           Dec(Linie);
  1100.                           OutboundPtr:=OutboundPtrType(outbound.Prev(OutboundPtr));
  1101.                           IF Linie < 2 THEN
  1102.                           BEGIN
  1103.                             FirstLine:=OutboundPtrType(Outbound.Prev(FirstLine));
  1104.                             WriteOutbound;
  1105.                           END ELSE
  1106.                             WriteLine(OutboundPtr,Linie, FALSE);
  1107.                         END;
  1108.                  Down : IF (OutboundPtr <> NIL) AND (outbound.next(OutboundPtr) <> NIL) THEN
  1109.                         BEGIN
  1110.                           WriteLine(OutboundPtr, Linie, FALSE);
  1111.                           Inc(Linie);
  1112.                           OutboundPtr:=OutboundPtrType(outbound.next(OutboundPtr));
  1113.                           IF Linie > ScreenHeight-5 THEN
  1114.                           BEGIN
  1115.                             FirstLine:=OutboundPtrType(Outbound.Next(FirstLine));
  1116.                             WriteOutbound;
  1117.                           END ELSE
  1118.                             WriteLine(OutboundPtr,Linie,FALSE);
  1119.                         END;
  1120.                  PgDn : IF Outbound.Size>0 THEN
  1121.                         BEGIN
  1122.                           l:=2;
  1123.                           WHILE (Outboundptr <> NIL) AND (Outbound.Next(OutboundPtr)<>Nil) And (l<ScreenHeight-4) DO
  1124.                           BEGIN
  1125.                             Inc(linie); Inc(l);
  1126.                             OutboundPtr:=OutboundPtrType(Outbound.next(OutboundPtr));
  1127.                             IF Linie>ScreenHeight-5 THEN
  1128.                             BEGIN
  1129.                               FirstLine:=OutboundPtr;
  1130.                               Linie:=2;
  1131.                             END;
  1132.                           END;
  1133.                           WriteOutbound;
  1134.                         END;
  1135.                  PgUp : IF Outbound.Size>0 THEN
  1136.                         BEGIN
  1137.                           l:=ScreenHeight-4;
  1138.                           WHILE (outboundptr <> NIL) AND (Outbound.Prev(OutboundPtr)<>Nil) And (l>2) DO
  1139.                           BEGIN
  1140.                             Dec(Linie); Dec(l);
  1141.                             OutboundPtr:=OutboundPtrType(Outbound.prev(OutboundPtr));
  1142.                             IF Linie<2 THEN
  1143.                             BEGIN
  1144.                               IF Outbound.Prev(FirstLine)<>Nil THEN FirstLine:=OutboundPtrType(Outbound.prev(FirstLine));
  1145.                               Linie:=2;
  1146.                             END;
  1147.                           END;
  1148.                           WriteOutbound;
  1149.                         END;
  1150.                  Home : IF Outbound.Size>0 THEN
  1151.                         BEGIN
  1152.                           OutboundPtr:=OutboundPtrType(Outbound.Head);
  1153.                           FirstLine:=OutboundPtr;
  1154.                           WriteOutbound;
  1155.                         END;
  1156.                  EndKey:IF Outbound.Size>0 THEN
  1157.                         BEGIN
  1158.                           OutboundPtr:=OutboundPtrType(Outbound.Tail);
  1159.                           FirstLine:=OutboundPtr;
  1160.                           Linie:=ScreenHeight-5;
  1161.                           WHILE (Outbound.Prev(FirstLine)<>Nil) And (Linie>2) DO
  1162.                           BEGIN
  1163.                             Dec(Linie);
  1164.                             FirstLine:=OutboundPtrType(Outbound.Prev(FirstLine));
  1165.                           END;
  1166.                           WriteOutbound;
  1167.                         END;
  1168.                  Del,
  1169.                  F2 :   DeleteEntry;
  1170.                  F3 :   RequestFile;
  1171.                  Ins,
  1172.                  F4 :   SendFile;
  1173.                  F5 :   ReAddress;
  1174.                  F6 :   ChangeStat;
  1175.                  F7 :   ViewFile;
  1176.                  F8 :   Poll;
  1177.                  F9 :   FileUpdateRequest;
  1178.                  F10 :  GlobalCmd;
  1179.                END;
  1180.         END;
  1181.       UNTIL InKey=Esc;
  1182.     END;
  1183.  
  1184.     PROCEDURE RenamePkt(CONST Path: PathStr; CONST FName: S12);
  1185.     VAR
  1186.       PktHead : TPktHeader;
  1187.       f       : TBufTextFile;
  1188.       Orig,
  1189.       Dest    : TFidoAddress;
  1190.     BEGIN
  1191.       IF f.Init(Path+FName, SOpenread+ShareDenyNone, 10240) THEN
  1192.       BEGIN
  1193.         IF f.GetSize>=SizeOf(PktHead) THEN
  1194.         BEGIN
  1195.           f.Read(PktHead,SizeOf(PktHead));
  1196.           f.Done;
  1197.           GetPktHeadInfo(PktHead,Orig,Dest);
  1198.           RenameFile(Path+FName, HoldFileName(Dest,TRUE)+'OUT');
  1199.         END ELSE
  1200.           f.Done;
  1201.       END;
  1202.     END;
  1203.  
  1204.     PROCEDURE ScanOutbound;
  1205.     VAR
  1206.       ss,ZoneOut, OutName : PathStr;
  1207.       Try, Count     : Byte;
  1208.       t              : Char;
  1209.       f              : TBufTextFile;
  1210.       FName, ext, p, InStr : String;
  1211.       i, GlobZone, GlobNet, GlobNode, test : Integer;
  1212.       Srec, Sr1, sr,sr3  : SEARCHREC;
  1213.       UnDialableRec  : TUndialable;
  1214.       UnDialableFile,
  1215.       BadWaZOOFile   : PSimpDB;
  1216.       BadWaZOORec    : TBadWaZOO;
  1217.       GotOne         : Boolean;
  1218.       Wait           : PWait;
  1219.  
  1220.       PROCEDURE SearchDir;
  1221.       VAR
  1222.         a    : Byte;
  1223.       BEGIN
  1224.         FindFirst(ZoneOut+'*.PKT',Archive,Sr) ;
  1225.         IF (DosError=0) And (Confirm('Orphan packets found, rename','Y',13)) THEN
  1226.         BEGIN
  1227.           REPEAT
  1228.             RenamePkt(ZoneOut,Sr.Name);
  1229.             FindNext(Sr);
  1230.             Wait^.Animate;
  1231.           UNTIL DosError<>0;
  1232.         END;
  1233.         FindClose(Sr);
  1234.  
  1235.         FOR a:=1 TO 5 DO
  1236.         BEGIN
  1237.           FindFirst(ZoneOut+'*.'+Mail[a]+'UT', archive, sr);
  1238.           WHILE DOSERROR = 0 DO
  1239.           BEGIN
  1240.             IF Sr.Size<>0 THEN
  1241.             BEGIN
  1242.               New(OutboundPtr, Init);
  1243.               IF OutboundPtr<>NIL THEN
  1244.               BEGIN
  1245.                 WITH OutboundPtr^ DO
  1246.                 BEGIN
  1247.                   Name:=sr.Name;
  1248.                   Address.Zone:=GlobZone;
  1249.                   Address.Zone:=GlobZone;
  1250.                   IF GlobNet=0 THEN
  1251.                   BEGIN
  1252.                     Val('$'+Copy(sr.Name, 1, 4), Address.Net, test);
  1253.                     Val('$'+Copy(sr.Name, 5, 4), Address.Node, test);
  1254.                     Address.Point:=0;
  1255.                   END ELSE
  1256.                   BEGIN
  1257.                     Address.Net:=GlobNet;
  1258.                     Address.Node:=GlobNode;
  1259.                     Val('$'+Copy(sr.Name, 5, 4), Address.Point, test);
  1260.                   END;
  1261.                   stat:=mail[a];
  1262.                   typ:='B';
  1263.                   siz:=sr.size;
  1264.                 END;
  1265.                 InsertEntry;
  1266.               END ELSE
  1267.                 AddLog('!', 'OutMan: Out of memory');
  1268.             END;
  1269.             Wait^.Animate;
  1270.             FindNext(sr);
  1271.           END;
  1272.           FindClose(Sr);
  1273.         END;
  1274.         FindFirst(ZoneOut+'*.REQ', archive, sr);
  1275.         WHILE DOSError = 0 DO
  1276.         BEGIN
  1277.           IF (sr.size>0) AND (f.Init(ZoneOut+sr.Name, SOpenread+ShareDenyNone, 10240)) THEN
  1278.           BEGIN
  1279.             GotOne:=False;
  1280.             WHILE NOT f.EoF DO
  1281.             BEGIN
  1282.               f.ReadLn(InStr);
  1283.               InStr:=StUpCase(InStr);
  1284.               IF (InStr[1] <> ';') AND (Length(InStr) > 0) THEN
  1285.               BEGIN
  1286.                 GotOne:=True;
  1287.                 t:='R';
  1288.                 Try:=Pos(' ',InStr);
  1289.                 IF (Try>0) And (pos('-', InStr)>Try) THEN t:='O';
  1290.                 IF (Try>0) And (pos('+', InStr)>Try) THEN t:='U';
  1291.                 IF Try >0  THEN InStr:=Copy(InStr, 1, Try-1);
  1292.                 New(OutboundPtr,Init);
  1293.                 IF OutboundPtr<>NIL THEN
  1294.                 BEGIN
  1295.                   WITH OutboundPtr^ DO
  1296.                   BEGIN
  1297.                     FSplit(InStr, p, FName, ext);
  1298.                     Name:=FName+ext;
  1299.                     path:=p;
  1300.                     Address.Zone:=GlobZone;
  1301.                     IF GlobNet=0 THEN
  1302.                     BEGIN
  1303.                       Val('$'+Copy(sr.Name, 1, 4), Address.Net, test);
  1304.                       Val('$'+Copy(sr.Name, 5, 4), Address.Node, test);
  1305.                       Address.Point:=0;
  1306.                     END ELSE
  1307.                     BEGIN
  1308.                       Address.Net:=GlobNet;
  1309.                       Address.Node:=GlobNode;
  1310.                       Val('$'+Copy(sr.Name, 5, 4), Address.Point, test);
  1311.                     END;
  1312.                     typ:=t;
  1313.                     siz:=0;
  1314.                   END;
  1315.                   InsertEntry;
  1316.                 END ELSE
  1317.                   AddLog('!', 'OutMan: Out of memory');
  1318.               END;
  1319.               Wait^.Animate;
  1320.             END;
  1321.             f.Done;
  1322.             IF NOT GotOne THEN DeleteFile(ZoneOut+sr.Name);
  1323.           END;
  1324.           FindNext(sr);
  1325.         END;
  1326.         FindClose(sr);
  1327.         FOR a:=1 TO 5 DO
  1328.         BEGIN
  1329.           FINDFIRST(ZoneOut+'*.'+Attach[a]+'LO', archive, sr);
  1330.           WHILE DOSERROR = 0 DO
  1331.           BEGIN
  1332.             Count:=0;
  1333.             IF (sr.size>0) AND (f.Init(ZoneOut+sr.Name, SOpenread+ShareDenyNone, 10240)) THEN
  1334.             BEGIN
  1335.               WHILE NOT F.EoF DO
  1336.               BEGIN
  1337.                 f.ReadLn(InStr);
  1338.                 InStr:=StUpCase(InStr);
  1339.                 IF (Length(InStr)>0) AND (InStr[1]<>';') AND (InStr[1]<>'~') THEN
  1340.                 BEGIN
  1341.                   New(OutboundPtr,Init);
  1342.                   IF OutboundPtr<>NIL THEN
  1343.                   BEGIN
  1344.                     IF (InStr[1] = '#') OR (InStr[1] = '^') THEN
  1345.                     BEGIN
  1346.                       OutboundPtr^.DoAfter:=InStr[1];
  1347.                       InStr:=Copy(InStr, 2, Length(InStr) - 1);
  1348.                     END;
  1349.                     WITH OutboundPtr^ DO
  1350.                     BEGIN
  1351.                       FSplit(InStr, p, FName, ext);
  1352.                       Name:=FName+ext;
  1353.                       Address.Zone:=GlobZone;
  1354.                       IF GlobNet=0 THEN
  1355.                       BEGIN
  1356.                         Val('$'+Copy(sr.Name, 1, 4), Address.Net, test);
  1357.                         Val('$'+Copy(sr.Name, 5, 4), Address.Node, test);
  1358.                         Address.Point:=0;
  1359.                       END ELSE
  1360.                       BEGIN
  1361.                         Address.Net:=GlobNet;
  1362.                         Address.Node:=GlobNode;
  1363.                         Val('$'+Copy(sr.Name, 5, 4), Address.Point, test);
  1364.                       END;
  1365.                       stat:=Attach[a];
  1366.                       FINDFIRST(p+FName+ext, AnyFile, Sr1);
  1367.                       IF DOSError=0 THEN siz:=Sr1.size ELSE siz:=0;
  1368.                       FindClose(Sr1);
  1369.                       IF StUpCase(p) = StUpCase(ZoneOut) THEN p:='';
  1370.                       path:=p;
  1371.                       IF p = '' THEN typ:='M' ELSE typ:='F';
  1372.                     END;
  1373.                     Inc(Count);
  1374.                     InsertEntry;
  1375.                   END ELSE
  1376.                     AddLog('!', 'OutMan: Out of memory');
  1377.                 END;
  1378.                 Wait^.Animate;
  1379.               END;
  1380.               f.Done;
  1381.             END;
  1382.             IF Count=0 THEN
  1383.             BEGIN
  1384.               New(OutboundPtr,Init);
  1385.               IF OutboundPtr<>NIL THEN
  1386.               BEGIN
  1387.                 WITH OutboundPtr^ DO
  1388.                 BEGIN
  1389.                   Name:='';
  1390.                   path:='';
  1391.                   Address.Zone:=GlobZone;
  1392.                   IF GlobNet=0 THEN
  1393.                   BEGIN
  1394.                     Val('$'+Copy(sr.Name, 1, 4), Address.Net, test);
  1395.                     Val('$'+Copy(sr.Name, 5, 4), Address.Node, test);
  1396.                     Address.Point:=0;
  1397.                   END ELSE
  1398.                   BEGIN
  1399.                     Address.Net:=GlobNet;
  1400.                     Address.Node:=GlobNode;
  1401.                     Val('$'+Copy(sr.Name, 5, 4), Address.Point, test);
  1402.                   END;
  1403.                   stat:=Attach[a];
  1404.                   siz:=0;
  1405.                   typ:='P';
  1406.                 END;
  1407.                 InsertEntry;
  1408.               END ELSE
  1409.                 AddLog('!', 'OutMan: Out of memory');
  1410.             END;
  1411.             FindNext(sr);
  1412.           END;
  1413.           FindClose(sr);
  1414.         END;
  1415.       END;
  1416.  
  1417.     BEGIN
  1418.       New(Wait, Init((ScreenHeight DIV 2)-2, 3, 'Scanning outbound'));
  1419.       FINDFIRST(cfg.outbound+'.*', Directory, Srec);
  1420.       OutName:=JustFileName(cfg.outbound);
  1421.       GlobNet:=0; GlobNode:=0;
  1422.       WHILE DOSERROR=0 DO
  1423.       BEGIN
  1424.         Test:=0;
  1425.         IF Srec.Name=OutName THEN
  1426.           GlobZone:=cfg.Addresses[Cfg.MainAdrNum].Zone
  1427.         ELSE
  1428.         BEGIN
  1429.           p:=Copy(Srec.Name, pos('.', Srec.Name)+1, Length(Srec.Name) - pos('.', Srec.Name)+1);
  1430.           Val('$'+p, GlobZone, test);
  1431.           IF GlobZone=Cfg.Addresses[Cfg.MainAdrNum].Zone THEN
  1432.           BEGIN
  1433.             FindNext(SRec);
  1434.             Continue;
  1435.           END;
  1436.         END;
  1437.         IF (Test=0) AND (GlobZone<>0) THEN
  1438.         BEGIN
  1439.           ZoneOut:=HoldAreaNameMunge(GlobZone,False);
  1440.           SearchDir;
  1441.           FindFirst(ZoneOut+'*.PNT',Directory,sr3);
  1442.           ss:=ZoneOut;
  1443.           WHILE DosError=0 DO
  1444.           BEGIN
  1445.             ZoneOut:=AddBackSlash(ss+Sr3.Name);
  1446.             Val('$'+Copy(sr3.Name, 1, 4), GlobNet, i);
  1447.             Val('$'+Copy(sr3.Name, 5, 4), GlobNode, i);
  1448.             SearchDir;
  1449.             FindNext(sr3);
  1450.           END;
  1451.           FindClose(sr3);
  1452.         END;
  1453.         GlobNet:=0; GlobNode:=0;
  1454.         Wait^.Animate;
  1455.         FINDNEXT(Srec);
  1456.       END;
  1457.       FindClose(SRec);
  1458.  
  1459.       New(BadWaZOOFile, Open(StartPath+PoPBadWaZooFileName, SizeOf(TBadWaZOO), False));
  1460.       IF BadWaZOOFile<>Nil THEN
  1461.       BEGIN
  1462.         WHILE BadWaZOOFile^.NextRec(BadWaZOORec, NoKeep) DO
  1463.         BEGIN
  1464.           WITH BadWaZOORec DO
  1465.           BEGIN
  1466.             FindFirst(Cfg.Inbound[BadWaZooRec.NodeStat]+NewName, AnyFile, Sr);
  1467.             IF DOSError<>0 THEN Sr.Size:=0;
  1468.             FindClose(Sr);
  1469.             New(OutboundPtr,Init);
  1470.             IF OutboundPtr<>NIL THEN
  1471.             BEGIN
  1472.               OutboundPtr^.Name:=NewName;
  1473.               OutboundPtr^.Address:=BadWaZooRec.Address;
  1474.               OutboundPtr^.stat:=' ';
  1475.               OutboundPtr^.siz:=FSize;
  1476.               OutboundPtr^.path:=FName+' ('+Long2Str(Sr.Size)+') -> ';
  1477.               OutboundPtr^.typ:='W';
  1478.               InsertEntry;
  1479.             END ELSE
  1480.               AddLog('!', 'OutMan: Out of memory');
  1481.             Wait^.Animate;
  1482.           END;
  1483.         END;
  1484.         Dispose(BadWaZOOFile, Close);
  1485.       END;
  1486.  
  1487.       New(UnDialableFile, Open(StartPath+PoPUndialFileName, SizeOf(TUnDialable), False));
  1488.       IF UnDialableFile<>Nil THEN
  1489.       BEGIN
  1490.         WHILE UnDialableFile^.NextRec(UnDialableRec, NoKeep) DO
  1491.         BEGIN
  1492.           WITH UnDialableRec DO
  1493.           BEGIN
  1494.             New(OutboundPtr,Init);
  1495.             IF OutboundPtr<>NIL THEN
  1496.             BEGIN
  1497.               OutboundPtr^.Name:='';
  1498.               OutboundPtr^.Address:=UndialableRec.Address;
  1499.               OutboundPtr^.stat:=' ';
  1500.               OutboundPtr^.siz:=0;
  1501.               OutboundPtr^.path:='NoConnect: '+LongIntForm('##',NoConnect)+' BadWaZOO: '+LongIntForm('###',BadWaZOO);
  1502.               OutboundPtr^.typ:='Z';
  1503.               InsertEntry;
  1504.             END ELSE
  1505.               AddLog('!', 'OutMan: Out of memory');
  1506.           END;
  1507.           Wait^.Animate;
  1508.         END;
  1509.         Dispose(UnDialableFile, Close);
  1510.       END;
  1511.       Dispose(Wait, Done);
  1512.     END;
  1513.  
  1514.   BEGIN
  1515.     FillChar(Call, SizeOf(Call), 0);
  1516.     IF Not SetInterCom(ICOutman,Call,True) THEN Exit;
  1517.     Outbound.Init;
  1518.     WITH cfg.color[2] DO
  1519.     BEGIN
  1520.       mywin(Temp, 1, 2, 80, ScreenHeight-2, 2, 'Outbound Manager',False);
  1521.       Temp^.wFastText('   Address    Type    Stat       Size  Filename                               ', 1, 1);
  1522.       mywin(Temp3, 1, ScreenHeight-1, 80, ScreenHeight, 2, '',False);
  1523.       temp3^.wfasttext('F1=Help          F2=Delete      F3=Request     F4=Send File     F5=ReAddress', 1, 2);
  1524.       temp3^.wfasttext('F6=Change Stat   F7=View File   F8=Poll        F9=Upd. Req.     F0=Global Cmd.', 2, 2);
  1525.     END;
  1526.     ScanOutbound;
  1527.     Temp^.Select;
  1528.  
  1529.     OutboundPtr:=OutboundPtrType(OutBound.Head);
  1530.     FirstLine:=OutboundPtr;
  1531.     MarkCount:=0;
  1532.     WriteOutbound;
  1533.  
  1534.     BrowseList;
  1535.  
  1536.     KillWindow(Temp3);
  1537.     KillWindow(Temp);
  1538.     Outbound.Done;
  1539.   END;
  1540.  
  1541. END.
  1542.